/*
* 公司：Leita Tech
* 版权信息：雷塔所有
* 任务：用于和Qml交换数据的通用的List模型
* 描述：
* 作者：李大平
* 日期：2020/06/04
*
*/

#include "model/LTListModel.h"
#include <algorithm>

LTListModel::Data LTListModel::null_data_;

LTListModel::LTListModel(const QHash<int, QByteArray> &role_names, QObject *parent/* = nullptr*/) :
    QAbstractListModel (parent)
{
    role_names_ = role_names;
    QHashIterator<int, QByteArray> role_pair(role_names_);
     while (role_pair.hasNext()) {
         role_pair.next();
         role_indices_.insert(role_pair.value(), role_pair.key());
     }
}
LTListModel::LTListModel(const QVector<QByteArray> &role_names, QObject *parent/* = nullptr*/) :
    QAbstractListModel (parent)
{
    QHash<int, QByteArray> real_role_names;
    int i = 0;
    for(auto role_name : role_names)
        real_role_names[Qt::UserRole + i++] = role_name;

    role_names_ = real_role_names;
    QHashIterator<int, QByteArray> role_pair(real_role_names);
     while (role_pair.hasNext()) {
         role_pair.next();
         role_indices_.insert(role_pair.value(), role_pair.key());
     }
}

int LTListModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return datas_.size();
}
QVariant LTListModel::data(const QModelIndex &index, int role) const
{
    if(!index.isValid())
        return QVariant();
    if(index.row() >= datas_.size())
        return QVariant();
    Data data = getData(index.row());
    QByteArray role_name = getRoleName(role);
    return data.value(role_name);
}
QHash<int, QByteArray> LTListModel::roleNames() const
{
    return role_names_;
}
bool LTListModel::setData(const QModelIndex &index, const QVariant &value, int role/* = Qt::EditRole*/)
{
    if(index.isValid() && index.row() < datas_.size())
    {
        Data &data = datas_[index.row()];
        QByteArray role_name = getRoleName(role);
        if(role_name.length() != 0)
        {
            if(data.value(role_name) != value)
            {
                data[role_name] = value;
                return true;
            }
        }
    }
    return QAbstractListModel::setData(index, value, role);
}
bool LTListModel::deleteData(int index)
{
    if(index < 0 || index >= datas_.size())
        return false;
    if(datas_.empty())
        return false;

    beginRemoveRows(createIndex(index, 0).parent(), index, index);
    datas_.removeAt(index);
    endRemoveRows();

    return true;
}

void LTListModel::deleteDatas(std::function<bool (const LTListModel::Data &)> cond)
{
    if(cond == nullptr)
        return;
    for(int i = 0; i < datas_.size();)
    {
        if(cond(datas_[i]))
        {
            deleteData(i);
        }
        else
            i++;
    }
}
int LTListModel::addData(const Data &data)
{
    if(datas_.empty())
    {
        beginResetModel();
        datas_.append(data);
        endResetModel();
    }
    else
    {
        beginInsertRows(createIndex(datas_.size() - 1, 0).parent(), datas_.size(), datas_.size());
        datas_.append(data);
        endInsertRows();
    }
    return data.size() - 1;
}
void LTListModel::setData(int index,const QVariant &value, const QByteArray &role)
{
    if(index < 0 || index >= datas_.size())
        return;
    if(datas_.empty())
        return;
    int role_index = role_indices_.value(role, 0);
    if(role_index == 0)
        return;
    datas_[index][role] = value;
    emit dataChanged(createIndex(index,0), createIndex(index,0), {role_index});
}

void LTListModel::setData(int index, const LTListModel::Data &data)
{
    if(index < 0 || index >= datas_.size())
        return;
    if(datas_.empty())
        return;
    datas_[index] = data;
    emit dataChanged(createIndex(index,0), createIndex(index,0));
}
void LTListModel::clearDatas()
{
    if(datas_.empty())
        return;
    beginResetModel();
    datas_.clear();
    endResetModel();
}
const LTListModel::Data &LTListModel::getData(int index) const
{
    if(index < 0 || index >= datas_.size())
        return null_data_;
    return datas_[index];
}

int LTListModel::getData(const QByteArray &role, const QVariant &role_value)
{
    int i = 0;
    for(auto &data : datas_)
    {
        if(data.contains(role) && data.value(role) == role_value)
            return i;
        i++;
    }
    return -1;
}

int LTListModel::makeData(const QByteArray &role, const QVariant &role_value)
{
    int i = 0;
    for(auto &data : datas_)
    {
        if(data.contains(role) && data.value(role) == role_value)
            return i;
        i++;
    }
    addData(Data({{role, role_value}}));
    return i;
}

bool LTListModel::hasData(const QByteArray &role, const QVariant &role_value) const
{
    for(auto &data : datas_)
    {
        if(data.contains(role) && data.value(role) == role_value)
            return true;
    }
    return false;
}

QVariant LTListModel::getData(int _index, const QByteArray &role)
{
    if(_index >= datas_.size())
        return QVariant();
    return datas_[_index].value(role);
}
void LTListModel::sortDatas(const QByteArray &role, bool asscending/* = true*/)
{
    bool is_sorted = true;
    for(int i = 0; i < datas_.size() - 1; i++)
    {
        if(asscending)
         {
            if(datas_[i].value(role) > datas_[i + 1].value(role))
            {
                is_sorted = false;
                break;
            }
        }
        else
        {
            if(datas_[i].value(role) < datas_[i + 1].value(role))
            {
                is_sorted = false;
                break;
            }
        }
    }
    if(is_sorted)
        return;
    beginResetModel();
    std::sort(datas_.begin(),datas_.end(),[=](const Data &a, const Data &b){
        if(asscending)
            return a.value(role) < b.value(role);
        else
            return a.value(role) > b.value(role);
    });
    endResetModel();
}
void LTListModel::stableSortDatas(const QByteArray &role, bool asscending/* = true*/)
{
    bool is_sorted = true;
    for(int i = 0; i < datas_.size() - 1; i++)
    {
        if(asscending)
         {
            if(datas_[i].value(role) > datas_[i + 1].value(role))
            {
                is_sorted = false;
                break;
            }
        }
        else
        {
            if(datas_[i].value(role) < datas_[i + 1].value(role))
            {
                is_sorted = false;
                break;
            }
        }
    }
    if(is_sorted)
        return;
    beginResetModel();
    std::stable_sort(datas_.begin(),datas_.end(),[=](const Data &a, const Data &b){
        if(asscending)
            return a.value(role) < b.value(role);
        else
            return a.value(role) > b.value(role);
    });
    endResetModel();
}
QByteArray LTListModel::getRoleName(int role) const
{
    return role_names_.value(role);
}

void LTListModel::insertData(QVariant ini_val)
{
    LTListModel::Data data;
    QHash<int, QByteArray> role_names = roleNames();
    for(auto &it : role_names)
    {
        data.insert(it, ini_val);
    }
    if(datas_.empty())
    {
        beginResetModel();
        datas_.append(data);
        endResetModel();
    }
    else
    {

        datas_.push_front(data);  // 從第一位插入  柳黎明
        beginInsertRows(createIndex(0, 0).parent(),0, 0);
        endInsertRows();
    }
}
